﻿using GMS.NET.Core.Options;
using GMS.NET.Encrypt;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace GMS.NET.Core.ApiSafe
{
    /// <summary>
    /// api安全参数
    /// </summary>
    public class ApiSafeHeader : IValidatableObject
    {
        /// <summary>
        /// 时间戳
        /// </summary>
        [Required(ErrorMessage = "缺少时间戳"), MaxLength(10, ErrorMessage = "10位时间戳格式"), MinLength(10, ErrorMessage = "10位时间戳格式")]
        public string? Timestamp { get; set; }
        /// <summary>
        /// 签名
        /// </summary>
        [Required(ErrorMessage = "缺少参数签名")]
        public string? Signature { get; set; }
        /// <summary>
        /// 自定义校验
        /// </summary>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            #region 校验请求时效性
            var options = App.GetOptions<ApplicationOptions>();
            if (options.ApiValidation!.TimeRange > 0)
            {
                if (Regex.IsMatch(Timestamp!, "[0-9]") == false)
                {
                    yield return new ValidationResult("请求时效格式错误", new[] { nameof(Timestamp) });
                }
                else
                {
                    DateTime requesttime = new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(Convert.ToDouble(Timestamp));
                    TimeSpan diffs = DateTime.Now - requesttime;
                    if (diffs.Seconds < 0 || diffs.Seconds > options.ApiValidation!.TimeRange)
                    {
                        yield return new ValidationResult("请求时效异常", new[] { nameof(Timestamp) });
                    }
                }
            }
            #endregion

            #region 校验签名合法性
            var CheckInfo = $"{Timestamp}&{options.ApiValidation.ServerKey}";
            var CheckInfoOrder = CheckInfo.OrderBy(x => x);
            var SHA512CheckInfo = $"{string.Join("", CheckInfoOrder)}";
            var CheckInfoSHA512Upper = SHA.Hash512(SHA512CheckInfo);
            if (Signature != CheckInfoSHA512Upper)
                yield return new ValidationResult("非法签名", new[] { nameof(Signature) });
            #endregion
        }
    }
}
